/***************************************************************************
 *   Copyright (C) 2007 by Grzegorz Latarowski, Maciej Gajewski            *
 *   g.latarowski@gmail.com                                                *
 *   maciej.gajewski0@gmail.com                                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

// Qt
#include <QtGlobal>
#include <QRgb>
#include <QImage>
#include <QVariant>
#include <QFile>
#include <QColor>

// j2k-codec
#include "j2k-codec.h"

// local
#include "gjpeg2khandler.h"


const char J2K_KEY[] = "lNYZ28mCTSzRwPbOvgB!gbxf2kXuL!czuWt2xOcNIqTqpTx?HKG5dNCvBrB9lGKBiT";



// ===========================================================================
//                             GJpeg2kHandler
// ===========================================================================


// ------------------ GJpeg2kHandler::GJpeg2kHandler() -----------------------
GJpeg2kHandler::GJpeg2kHandler() : QImageIOHandler()
{
	J2K_Unlock( J2K_KEY );
}
// ---------------------------------------------------------------------------


// ----------------- GJpeg2kHandler::~GJpeg2kHandler() -----------------------
GJpeg2kHandler::~GJpeg2kHandler()
{
	// none
}
// ---------------------------------------------------------------------------


// --------------------- GJpeg2kHandler::canRead()----------------------------
bool GJpeg2kHandler::canRead() const
{
    return true;

	QIODevice * pDev = device();
	if ( ! pDev )
	{
		return false;
	}
		// pickup 16 bytes from device
	QByteArray prefix = pDev->peek(16);
	
		// chceck if it contains JPEG 2000 magic
	if( prefix.contains( "\x0d\x0a\x87\x0a" ) )
	{
		setFormat( "jp2" );
		return true;
	}
		// check jpeg codestream header
	else if( prefix.contains( "\xff\x4f\xff\x51" ) )
	{
		setFormat( "j2c" );
		return true;
	}

	return false;
}
// ---------------------------------------------------------------------------


// ------------------- GJpeg2kHandler::canRead() -----------------------------
bool GJpeg2kHandler::canRead( QIODevice * pDev )
{
	if ( !pDev )
	{
		return false;
	}
		// pickup 16 bytes from device
	QByteArray prefix = pDev->peek(16);
	
		// chceck if it contains JPEG 2000 magic
	if( prefix.contains( "\x0d\x0a\x87\x0a" ) )
	{
		return true;
	}
		// check jpeg codestream header
	else if( prefix.contains( "\xff\x4f\xff\x51" ) )
	{
		return true;
	}

	return false;
}
// ---------------------------------------------------------------------------


// ---------------------- GJpeg2kHandler::read() -----------------------------
bool GJpeg2kHandler::read( QImage *pOutImage )
{
	// create stream
	QIODevice * pDevice = device();
	QByteArray  buffer  = pDevice->readAll();
	
		// setup image 	
	J2K_Image j2k_image;
		// decode image
	QString fmt = format();
	if( ( fmt == "j2c" ) || ( fmt == "jp2" ) )
	{
		int j2k_err = j2k_image.easyDecode( (unsigned char *)buffer.data(), buffer.size(), "bpp=3" );
		if( j2k_err != J2KERR_SUCCESS )
		{
			qWarning( "GJpeg2kHandler::read: Can not decode j2k image." );
			return false;
		}
	}
	else
	{
		qWarning( "GJpeg2kHandler::read: unknown format: %s", qPrintable( fmt ) );
		return false;
	}
	
		// copy pixels 	
	int width  = j2k_image.width;
	int height = j2k_image.height;
	int bpp    = j2k_image.components;
	
		// convert image
	QImage image( QSize( width, height), QImage::Format_RGB32 );
	unsigned char * pBuffer = j2k_image.buffer;
	
	for( int y = 0; y < height; y++ )
	{
		quint32 * pLine = (quint32 *)image.scanLine( y );
		for( int x = 0; x < width; x++ )
		{
				// convert to RGB
			int R,G,B;
			B = *pBuffer++;
			G = *pBuffer++;
			R = *pBuffer++;
				// add to QImage
			*pLine = qRgb( R, G, B );
			pLine++;
		} // !x
	} // !y	
	
	* pOutImage = image;
	
		// success!
	return true;
}
// ---------------------------------------------------------------------------


// --------------------- GJpeg2kHandler::write() -----------------------------
bool GJpeg2kHandler::write( const QImage & /*image*/ )
{
	return false;
}
// ---------------------------------------------------------------------------


// --------------------- GJpeg2kHandler::supportsOption() --------------------
bool GJpeg2kHandler::supportsOption( ImageOption /*option*/ ) const
{
	return false;
}
// ---------------------------------------------------------------------------


// -------------------- GJpeg2kHandler::option() -----------------------------
QVariant GJpeg2kHandler::option( ImageOption /*option*/ ) const
{
	return QVariant();
}
// ---------------------------------------------------------------------------


// ------------------- GJpeg2kHandler::setOption() ---------------------------
void GJpeg2kHandler::setOption( ImageOption /*option*/,
								const QVariant & /*value*/
							  )
{
	// none
}
// ---------------------------------------------------------------------------




// eof
